`
https://leetcode.cn/problems/repeated-dna-sequences/
`

/**
 * @param {string} s
 * @return {string[]}
 */
var findRepeatedDnaSequences = function (s) {
  // 先把字符串转化成四进制的数字数组
  const nums = new Array(s.length);
  for (var i = 0; i < nums.length; i++) {
    switch (s.charAt(i)) {
      case 'A':
        nums[i] = 0;
        break;
      case 'G':
        nums[i] = 1;
        break;
      case 'C':
        nums[i] = 2;
        break;
      case 'T':
        nums[i] = 3;
        break;
    }
  }
  // 记录重复出现的哈希值
  const seen = new Set();
  // 记录重复出现的字符串结果
  const res = new Set();

  // 数字位数
  const L = 10;
  // 进制
  const R = 4;
  // 存储 R^(L - 1) 的结果
  const RL = Math.pow(R, L - 1);
  // 维护滑动窗口中字符串的哈希值
  let windowHash = 0;

  // 滑动窗口代码框架，时间 O(N)
  let left = 0, right = 0;
  while (right < nums.length) {
    // 扩大窗口，移入字符，并维护窗口哈希值（在最低位添加数字）
    windowHash = R * windowHash + nums[right];
    right++;

    // 当子串的长度达到要求
    if (right - left == L) {
      // 根据哈希值判断是否曾经出现过相同的子串
      if (seen.has(windowHash)) {
        // 当前窗口中的子串是重复出现的
        res.add(s.substring(left, right));
      } else {
        // 当前窗口中的子串之前没有出现过，记下来
        seen.add(windowHash);
      }
      // 缩小窗口，移出字符，并维护窗口哈希值（删除最高位数字）
      windowHash = windowHash - nums[left] * RL;
      left++;
    }
  }
  // 转化成题目要求的 List 类型
  return Array.from(res);
};